home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / boot.lisp < prev    next >
Lisp/Scheme  |  1993-01-07  |  79KB  |  2,167 lines

  1. ;;;-*-Mode: LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27.  
  28. (in-package :pcl)
  29.  
  30. #|
  31.  
  32. The CommonLoops evaluator is meta-circular.  
  33.  
  34. Most of the code in PCL is methods on generic functions, including most of
  35. the code that actually implements generic functions and method lookup.
  36.  
  37. So, we have a classic bootstrapping problem.   The solution to this is to
  38. first get a cheap implementation of generic functions running, these are
  39. called early generic functions.  These early generic functions and the
  40. corresponding early methods and early method lookup are used to get enough
  41. of the system running that it is possible to create real generic functions
  42. and methods and implement real method lookup.  At that point (done in the
  43. file FIXUP) the function fix-early-generic-functions is called to convert
  44. all the early generic functions to real generic functions.
  45.  
  46. The cheap generic functions are built using the same funcallable-instance
  47. objects real generic-functions are made out of.  This means that as PCL
  48. is being bootstrapped, the cheap generic function objects which are being
  49. created are the same objects which will later be real generic functions.
  50. This is good because:
  51.   - we don't cons garbage structure
  52.   - we can keep pointers to the cheap generic function objects
  53.     during booting because those pointers will still point to
  54.     the right object after the generic functions are all fixed
  55.     up
  56.  
  57.  
  58.  
  59. This file defines the defmethod macro and the mechanism used to expand it.
  60. This includes the mechanism for processing the body of a method.  defmethod
  61. basically expands into a call to load-defmethod, which basically calls
  62. add-method to add the method to the generic-function.  These expansions can
  63. be loaded either during bootstrapping or when PCL is fully up and running.
  64.  
  65. An important effect of this structure is it means we can compile files with
  66. defmethod forms in them in a completely running PCL, but then load those files
  67. back in during bootstrapping.  This makes development easier.  It also means
  68. there is only one set of code for processing defmethod.  Bootstrapping works
  69. by being sure to have load-method be careful to call only primitives which
  70. work during bootstrapping.
  71.  
  72. |#
  73.  
  74. (proclaim '(notinline make-a-method
  75.               add-named-method              
  76.               ensure-generic-function-using-class
  77.  
  78.               add-method
  79.               remove-method
  80.               ))
  81.  
  82. (defvar *early-functions*
  83.     '((make-a-method early-make-a-method
  84.              real-make-a-method)
  85.       (add-named-method early-add-named-method
  86.                 real-add-named-method)
  87.       ))
  88.  
  89. ;;;
  90. ;;; For each of the early functions, arrange to have it point to its early
  91. ;;; definition.  Do this in a way that makes sure that if we redefine one
  92. ;;; of the early definitions the redefinition will take effect.  This makes
  93. ;;; development easier.
  94. ;;;
  95. ;;; The function which generates the redirection closure is pulled out into
  96. ;;; a separate piece of code because of a bug in ExCL which causes this not
  97. ;;; to work if it is inlined.
  98. ;;;
  99. (eval-when (load eval)
  100.  
  101. (defun redirect-early-function-internal (real early)
  102.   (setf (gdefinition real)
  103.     (set-function-name
  104.      #'(lambda (&rest args)
  105.          (apply (the function (symbol-function early)) args))
  106.      real)))
  107.  
  108. (dolist (fns *early-functions*)
  109.   (let ((name (car fns))
  110.     (early-name (cadr fns)))
  111.     (redirect-early-function-internal name early-name)))
  112.  
  113. )
  114.  
  115.  
  116. ;;;
  117. ;;; *generic-function-fixups* is used by fix-early-generic-functions to
  118. ;;; convert the few functions in the bootstrap which are supposed to be
  119. ;;; generic functions but can't be early on.
  120. ;;; 
  121. (defvar *generic-function-fixups*
  122.     '((add-method
  123.     ((generic-function method)                ;lambda-list
  124.      (standard-generic-function method)            ;specializers
  125.      real-add-method))                    ;method-function
  126.       (remove-method
  127.     ((generic-function method)
  128.      (standard-generic-function method)
  129.      real-remove-method))
  130.       (get-method
  131.         ((generic-function qualifiers specializers &optional (errorp t))
  132.      (standard-generic-function t t)
  133.      real-get-method))
  134.       (ensure-generic-function-using-class
  135.     ((generic-function function-specifier
  136.                &key generic-function-class environment
  137.                &allow-other-keys)
  138.      (generic-function t)
  139.      real-ensure-gf-using-class--generic-function)
  140.         ((generic-function function-specifier
  141.                &key generic-function-class environment
  142.                &allow-other-keys)
  143.      (null t)
  144.      real-ensure-gf-using-class--null))
  145.       (make-method-lambda
  146.        ((proto-generic-function proto-method lambda-expression environment)
  147.     (standard-generic-function standard-method t t)
  148.     real-make-method-lambda))
  149.       (make-method-initargs-form
  150.        ((proto-generic-function proto-method lambda-expression lambda-list environment)
  151.     (standard-generic-function standard-method t t t)
  152.     real-make-method-initargs-form))
  153.       (compute-effective-method
  154.        ((generic-function combin applicable-methods)
  155.     (generic-function standard-method-combination t)
  156.     standard-compute-effective-method))
  157.       ))
  158.  
  159.  
  160. ;;;
  161. ;;;
  162. ;;;
  163. (defmacro defgeneric (function-specifier lambda-list &body options)
  164.   (expand-defgeneric function-specifier lambda-list options))
  165.  
  166. (defun expand-defgeneric (function-specifier lambda-list options)
  167.   (when (listp function-specifier) (do-standard-defsetf-1 (cadr function-specifier)))
  168.   (let ((initargs ()))
  169.     (flet ((duplicate-option (name)
  170.          (error "The option ~S appears more than once." name)))
  171.       ;;
  172.       ;; INITARG takes this screwy new argument to get around a bad
  173.       ;; interaction between lexical macros and setf in the Lucid
  174.       ;; compiler.
  175.       ;; 
  176.       (macrolet ((initarg (key &optional new)
  177.            (if new
  178.                `(setf (getf initargs ,key) ,new)
  179.                `(getf initargs ,key))))
  180.     (dolist (option options)
  181.       (ecase (car option)
  182.         (:argument-precedence-order
  183.           (if (initarg :argument-precedence-order)
  184.           (duplicate-option :argument-precedence-order)
  185.           (initarg :argument-precedence-order `',(cdr option))))
  186.         (declare
  187.           (initarg :declarations
  188.                (append (cdr option) (initarg :declarations))))
  189.         (:documentation
  190.           (if (initarg :documentation)
  191.           (duplicate-option :documentation)
  192.           (initarg :documentation `',(cadr option))))
  193.         (:method-combination
  194.           (if (initarg :method-combination)
  195.           (duplicate-option :method-combination)
  196.           (initarg :method-combination `',(cdr option))))
  197.         (:generic-function-class
  198.           (if (initarg :generic-function-class)
  199.           (duplicate-option :generic-function-class)
  200.           (initarg :generic-function-class `',(cadr option))))
  201.         (:method-class
  202.           (if (initarg :method-class)
  203.           (duplicate-option :method-class)
  204.           (initarg :method-class `',(cadr option))))
  205.         (:method
  206.           (error
  207.         "DEFGENERIC doesn't support the :METHOD option yet."))))
  208.  
  209.     (let ((declarations (initarg :declarations)))
  210.       (when declarations (initarg :declarations `',declarations)))))
  211.     `(progn
  212.        (proclaim-defgeneric ',function-specifier ',lambda-list)
  213.        ,(make-top-level-form `(defgeneric ,function-specifier)
  214.       *defgeneric-times*
  215.       `(load-defgeneric ',function-specifier ',lambda-list ,@initargs)))))
  216.  
  217. (defun load-defgeneric (function-specifier lambda-list &rest initargs)
  218.   (when (listp function-specifier) (do-standard-defsetf-1 (cadr function-specifier)))
  219.   (apply #'ensure-generic-function
  220.      function-specifier
  221.      :lambda-list lambda-list
  222.      :definition-source `((defgeneric ,function-specifier)
  223.                   ,(load-truename))
  224.      initargs))
  225.  
  226.  
  227. ;;;
  228. ;;;
  229. ;;;
  230. (defmacro DEFMETHOD (&rest args &environment env)
  231.   #+(or (not :lucid) :lcl3.0)    
  232.   (declare (arglist name
  233.             {method-qualifier}*
  234.             specialized-lambda-list
  235.             &body body))
  236.   (multiple-value-bind (name qualifiers lambda-list body)
  237.       (parse-defmethod args)
  238.     (multiple-value-bind (proto-gf proto-method)
  239.     (prototypes-for-make-method-lambda name)
  240.       (expand-defmethod name proto-gf proto-method
  241.             qualifiers lambda-list body env))))
  242.  
  243. (defun prototypes-for-make-method-lambda (name)
  244.   (if (not (eq *boot-state* 'complete))      
  245.       (values nil nil)
  246.       (let ((gf? (and (gboundp name)
  247.               (gdefinition name))))
  248.     (if (or (null gf?)
  249.         (not (generic-function-p gf?)))
  250.         (values (class-prototype (find-class 'standard-generic-function))
  251.             (class-prototype (find-class 'standard-method)))
  252.         (values gf?
  253.             (class-prototype (or (generic-function-method-class gf?)
  254.                      (find-class 'standard-method))))))))
  255.  
  256. ;;;
  257. ;;; takes a name which is either a generic function name or a list specifying
  258. ;;; a setf generic function (like: (SETF <generic-function-name>)).  Returns
  259. ;;; the prototype instance of the method-class for that generic function.
  260. ;;;
  261. ;;; If there is no generic function by that name, this returns the default
  262. ;;; value, the prototype instance of the class STANDARD-METHOD.  This default
  263. ;;; value is also returned if the spec names an ordinary function or even a
  264. ;;; macro.  In effect, this leaves the signalling of the appropriate error
  265. ;;; until load time.
  266. ;;;
  267. ;;; NOTE that during bootstrapping, this function is allowed to return NIL.
  268. ;;; 
  269. (defun method-prototype-for-gf (name)      
  270.   (let ((gf? (and (gboundp name)
  271.           (gdefinition name))))
  272.     (cond ((neq *boot-state* 'complete) nil)
  273.       ((or (null gf?)
  274.            (not (generic-function-p gf?)))            ;Someone else MIGHT
  275.                                 ;error at load time.
  276.        (class-prototype (find-class 'standard-method)))
  277.       (t
  278.         (class-prototype (or (generic-function-method-class gf?)
  279.                  (find-class 'standard-method)))))))
  280.  
  281.  
  282. (defvar *optimize-asv-funcall-p* nil)
  283. (defvar *asv-readers*)
  284. (defvar *asv-writers*)
  285. (defvar *asv-boundps*)
  286.  
  287. (defun expand-defmethod (name proto-gf proto-method qualifiers lambda-list body env)
  288.   (when (listp name) (do-standard-defsetf-1 (cadr name)))
  289.   (let ((*make-instance-function-keys* nil)
  290.     (*optimize-asv-funcall-p* t)
  291.     (*asv-readers* nil) (*asv-writers* nil) (*asv-boundps* nil))
  292.     (declare (special *make-instance-function-keys*))
  293.     (multiple-value-bind (method-lambda unspecialized-lambda-list specializers)
  294.     (add-method-declarations name qualifiers lambda-list body env)
  295.       (multiple-value-bind (method-function-lambda initargs)
  296.       (make-method-lambda proto-gf proto-method method-lambda env)
  297.     (let ((initargs-form (make-method-initargs-form 
  298.                   proto-gf proto-method
  299.                   method-function-lambda initargs env)))
  300.       `(progn
  301.          (proclaim-defgeneric ',name ',lambda-list)
  302.          ,@(when *make-instance-function-keys*
  303.          `((get-make-instance-functions ',*make-instance-function-keys*)))
  304.          ,@(when (or *asv-readers* *asv-writers* *asv-boundps*)
  305.          `((initialize-internal-slot-gfs*
  306.             ',*asv-readers* ',*asv-writers* ',*asv-boundps*)))
  307.          ,(make-defmethod-form name qualifiers specializers
  308.                    unspecialized-lambda-list
  309.                    (if proto-method
  310.                        (class-name (class-of proto-method))
  311.                        'standard-method)
  312.                    initargs-form
  313.                                (getf (getf initargs ':plist)
  314.                          ':pv-table-symbol))))))))
  315.  
  316. (defun interned-symbol-p (x)
  317.   (and (symbolp x) (symbol-package x)))
  318.  
  319. (defun make-defmethod-form (name qualifiers specializers
  320.                  unspecialized-lambda-list method-class-name
  321.                  initargs-form &optional pv-table-symbol)
  322.   (let (fn fn-lambda)
  323.     (if (and (interned-symbol-p (if (consp name)
  324.                     (and (eq (car name) 'setf) (cadr name))
  325.                     name))
  326.          (every #'interned-symbol-p qualifiers)
  327.          (every #'(lambda (s)
  328.             (if (consp s)
  329.                 (and (eq (car s) 'eql) 
  330.                  (constantp (cadr s))
  331.                  (let ((sv (eval (cadr s))))
  332.                    (or (interned-symbol-p sv)
  333.                        (integerp sv)
  334.                        (standard-char-p sv))))
  335.                 (interned-symbol-p s)))
  336.             specializers)
  337.          (consp initargs-form)
  338.          (eq (car initargs-form) 'list*)
  339.          (memq (cadr initargs-form) '(:function :fast-function))
  340.          (consp (setq fn (caddr initargs-form)))
  341.          (eq (car fn) 'function)
  342.          (consp (setq fn-lambda (cadr fn)))
  343.          (eq (car fn-lambda) 'lambda))
  344.     (let* ((specls (mapcar #'(lambda (specl)
  345.                    (if (consp specl)
  346.                        `(,(car specl) ,(eval (cadr specl)))
  347.                        specl))
  348.                    specializers))
  349.            (mname `(,(if (eq (cadr initargs-form) ':function)
  350.                  'method 'fast-method)
  351.             ,name ,@qualifiers ,specls))
  352.            (mname-sym (intern (let ((*print-pretty* nil))
  353.                     (format nil "~S" mname)))))
  354.       `(eval-when ,*defmethod-times*
  355.         (defun ,mname-sym ,(cadr fn-lambda)
  356.           ,@(cddr fn-lambda))
  357.         ,(make-defmethod-form-internal 
  358.           name qualifiers `',specls
  359.           unspecialized-lambda-list method-class-name
  360.           `(list* ,(cadr initargs-form) #',mname-sym ,@(cdddr initargs-form))
  361.           pv-table-symbol)))
  362.     (make-top-level-form 
  363.      `(defmethod ,name ,@qualifiers ,specializers)
  364.      *defmethod-times*
  365.      (make-defmethod-form-internal 
  366.       name qualifiers 
  367.       `(list ,@(mapcar #'(lambda (specializer)
  368.                    (if (consp specializer)
  369.                    ``(,',(car specializer) ,,(cadr specializer))
  370.                    `',specializer))
  371.             specializers))
  372.       unspecialized-lambda-list method-class-name
  373.       initargs-form
  374.       pv-table-symbol)))))
  375.  
  376. (defun make-defmethod-form-internal (name qualifiers specializers-form
  377.                       unspecialized-lambda-list method-class-name
  378.                       initargs-form &optional pv-table-symbol)
  379.   `(load-defmethod
  380.     ',method-class-name
  381.     ',name
  382.     ',qualifiers
  383.     ,specializers-form
  384.     ',unspecialized-lambda-list
  385.     ,initargs-form
  386.     ;;Paper over a bug in KCL by passing the cache-symbol
  387.     ;;here in addition to in the list.
  388.     ',pv-table-symbol))
  389.  
  390. (defmacro make-method-function (method-lambda &environment env)
  391.   (make-method-function-internal method-lambda env))
  392.  
  393. (defun make-method-function-internal (method-lambda &optional env)
  394.   (multiple-value-bind (proto-gf proto-method)
  395.     (prototypes-for-make-method-lambda nil)
  396.     (multiple-value-bind (method-function-lambda initargs)
  397.     (make-method-lambda proto-gf proto-method method-lambda env)
  398.       (make-method-initargs-form proto-gf proto-method
  399.                  method-function-lambda initargs env))))
  400.  
  401. (defun add-method-declarations (name qualifiers lambda-list body env)
  402.   (multiple-value-bind (parameters unspecialized-lambda-list specializers)
  403.       (parse-specialized-lambda-list lambda-list)
  404.     (declare (ignore parameters))
  405.     (multiple-value-bind (documentation declarations real-body)
  406.     (extract-declarations body env)
  407.       (values `(lambda ,unspecialized-lambda-list
  408.          ,@(when documentation `(,documentation))
  409.          (declare (method-name ,(list name qualifiers specializers)))
  410.          (declare (method-lambda-list ,@lambda-list))
  411.          ,@declarations
  412.          ,@real-body)
  413.           unspecialized-lambda-list specializers))))
  414.  
  415. (defun real-make-method-initargs-form (proto-gf proto-method 
  416.                        method-lambda initargs env)
  417.   (declare (ignore proto-gf proto-method))
  418.   (unless (and (consp method-lambda) (eq (car method-lambda) 'lambda))
  419.     (error "The method-lambda argument to make-method-function, ~S,~
  420.             is not a lambda form" method-lambda))
  421.   (make-method-initargs-form-internal method-lambda initargs env))
  422.  
  423. (unless (fboundp 'make-method-initargs-form)
  424.   (setf (gdefinition 'make-method-initargs-form)
  425.     (symbol-function 'real-make-method-initargs-form)))
  426.  
  427. (defun real-make-method-lambda (proto-gf proto-method method-lambda env)
  428.   (declare (ignore proto-gf proto-method))
  429.   (make-method-lambda-internal method-lambda env))
  430.  
  431. (defun make-method-lambda-internal (method-lambda &optional env)
  432.   (unless (and (consp method-lambda) (eq (car method-lambda) 'lambda))
  433.     (error "The method-lambda argument to make-method-lambda, ~S,~
  434.             is not a lambda form" method-lambda))
  435.   (multiple-value-bind (documentation declarations real-body)
  436.       (extract-declarations (cddr method-lambda) env)
  437.     (let* ((name-decl (get-declaration 'method-name declarations))
  438.        (sll-decl (get-declaration 'method-lambda-list declarations))
  439.        (method-name (when (consp name-decl) (car name-decl)))
  440.        (generic-function-name (when method-name (car method-name)))
  441.        (specialized-lambda-list (or sll-decl (cadr method-lambda))))
  442.       (multiple-value-bind (parameters lambda-list specializers)
  443.       (parse-specialized-lambda-list specialized-lambda-list)
  444.     (let* ((required-parameters
  445.         (mapcar #'(lambda (r s) (declare (ignore s)) r)
  446.             parameters
  447.             specializers))
  448.            (slots (mapcar #'list required-parameters))
  449.            (calls (list nil))
  450.            (parameters-to-reference
  451.         (make-parameter-references specialized-lambda-list
  452.                        required-parameters
  453.                        declarations
  454.                        method-name
  455.                        specializers))
  456.            (class-declarations
  457.         `(declare
  458.           ,@(remove nil
  459.                 (mapcar #'(lambda (a s) (and (symbolp s)
  460.                              (neq s 't)
  461.                              `(class ,a ,s)))
  462.                     parameters
  463.                     specializers))))
  464.            (method-lambda
  465.           ;; Remove the documentation string and insert the
  466.           ;; appropriate class declarations.  The documentation
  467.           ;; string is removed to make it easy for us to insert
  468.           ;; new declarations later, they will just go after the
  469.           ;; cadr of the method lambda.  The class declarations
  470.           ;; are inserted to communicate the class of the method's
  471.           ;; arguments to the code walk.
  472.           `(lambda ,lambda-list
  473.              ,class-declarations
  474.              ,@declarations
  475.              (progn ,@parameters-to-reference)
  476.              (block ,(if (listp generic-function-name)
  477.                  (cadr generic-function-name)
  478.                  generic-function-name)
  479.                ,@real-body)))
  480.            (constant-value-p (and (null (cdr real-body))
  481.                       (constantp (car real-body))))
  482.            (constant-value (and constant-value-p
  483.                     (eval (car real-body))))
  484.            (plist (if (and constant-value-p
  485.                    (or (typep constant-value '(or number character))
  486.                    (and (symbolp constant-value)
  487.                     (symbol-package constant-value))))
  488.               (list :constant-value constant-value)
  489.               ()))
  490.            (applyp (dolist (p lambda-list nil)
  491.              (cond ((memq p '(&optional &rest &key))
  492.                 (return t))
  493.                    ((eq p '&aux)
  494.                 (return nil))))))
  495.         (multiple-value-bind (walked-lambda call-next-method-p closurep
  496.                         next-method-p-p)
  497.         (walk-method-lambda method-lambda required-parameters env 
  498.                     slots calls)
  499.           (multiple-value-bind (ignore walked-declarations walked-lambda-body)
  500.           (extract-declarations (cddr walked-lambda))
  501.         (declare (ignore ignore))
  502.         (when (or next-method-p-p call-next-method-p)
  503.           (setq plist (list* :needs-next-methods-p 't plist)))
  504.         (when (some #'cdr slots)
  505.           (multiple-value-bind (slot-name-lists call-list)
  506.               (slot-name-lists-from-slots slots calls)
  507.             (let ((pv-table-symbol (make-symbol "pv-table")))
  508.               (setq plist 
  509.                 `(,@(when slot-name-lists 
  510.                   `(:slot-name-lists ,slot-name-lists))
  511.                   ,@(when call-list
  512.                   `(:call-list ,call-list))
  513.                   :pv-table-symbol ,pv-table-symbol
  514.                   ,@plist))
  515.               (setq walked-lambda-body
  516.                 `((pv-binding (,required-parameters ,slot-name-lists
  517.                        ,pv-table-symbol)
  518.                    ,@walked-lambda-body))))))
  519.         (when (and (memq '&key lambda-list)
  520.                (not (memq '&allow-other-keys lambda-list)))
  521.           (let ((aux (memq '&aux lambda-list)))
  522.             (setq lambda-list (nconc (ldiff lambda-list aux)
  523.                          (list '&allow-other-keys)
  524.                          aux))))
  525.         (values `(lambda (.method-args. .next-methods.)
  526.                (simple-lexical-method-functions
  527.                    (,lambda-list .method-args. .next-methods.
  528.                 :call-next-method-p ,call-next-method-p 
  529.                 :next-method-p-p ,next-method-p-p
  530.                 :closurep ,closurep
  531.                 :applyp ,applyp)
  532.                  ,@walked-declarations
  533.                  ,@walked-lambda-body))
  534.             `(,@(when plist 
  535.                   `(:plist ,plist))
  536.               ,@(when documentation 
  537.                   `(:documentation ,documentation)))))))))))
  538.          
  539. (unless (fboundp 'make-method-lambda)
  540.   (setf (gdefinition 'make-method-lambda)
  541.     (symbol-function 'real-make-method-lambda)))
  542.  
  543. (defmacro simple-lexical-method-functions ((lambda-list method-args next-methods
  544.                             &rest lmf-options) 
  545.                        &body body)
  546.   `(progn
  547.      ,method-args ,next-methods
  548.      (bind-simple-lexical-method-macros (,method-args ,next-methods)
  549.        (bind-lexical-method-functions (,@lmf-options)
  550.          (bind-args (,lambda-list ,method-args)
  551.        ,@body)))))
  552.  
  553. (defmacro fast-lexical-method-functions ((lambda-list next-method-call args rest-arg
  554.                               &rest lmf-options)
  555.                      &body body)
  556.  `(bind-fast-lexical-method-macros (,args ,rest-arg ,next-method-call)
  557.     (bind-lexical-method-functions (,@lmf-options)
  558.       (bind-args (,(nthcdr (length args) lambda-list) ,rest-arg)
  559.         ,@body))))
  560.  
  561. (defmacro bind-simple-lexical-method-macros ((method-args next-methods) &body body)
  562.   `(macrolet ((call-next-method-bind (&body body)
  563.         `(let ((.next-method. (car ,',next-methods))
  564.                (,',next-methods (cdr ,',next-methods)))
  565.            .next-method. ,',next-methods
  566.            ,@body))
  567.           (call-next-method-body (cnm-args)
  568.         `(if .next-method.
  569.              (funcall (if (std-instance-p .next-method.)
  570.                   (method-function .next-method.)
  571.                   .next-method.) ; for early methods
  572.                   (or ,cnm-args ,',method-args)
  573.                       ,',next-methods)
  574.              (error "No next method.")))
  575.           (next-method-p-body ()
  576.             `(not (null .next-method.))))
  577.      ,@body))
  578.  
  579. (defstruct method-call
  580.   (function #'identity :type function)
  581.   call-method-args)
  582.  
  583. (defmacro invoke-method-call1 (function args cm-args)
  584.   `(let ((.function. ,function)
  585.      (.args. ,args)
  586.      (.cm-args. ,cm-args))
  587.      (if (and .cm-args. (null (cdr .cm-args.)))
  588.      (funcall .function. .args. (car .cm-args.))
  589.      (apply .function. .args. .cm-args.))))
  590.  
  591. (defmacro invoke-method-call (method-call restp &rest required-args+rest-arg)
  592.   `(invoke-method-call1 (method-call-function ,method-call)
  593.                         ,(if restp
  594.                  `(list* ,@required-args+rest-arg)
  595.                  `(list ,@required-args+rest-arg))
  596.                         (method-call-call-method-args ,method-call)))
  597.  
  598. (defstruct fast-method-call
  599.   (function #'identity :type function)
  600.   pv-cell
  601.   next-method-call
  602.   arg-info)
  603.  
  604. #-akcl
  605. (defmacro fmc-funcall (fn pv-cell next-method-call &rest args)
  606.   `(funcall ,fn ,pv-cell ,next-method-call ,@args))
  607.  
  608. (defmacro invoke-fast-method-call (method-call &rest required-args+rest-arg)
  609.   `(fmc-funcall (fast-method-call-function ,method-call)
  610.                 (fast-method-call-pv-cell ,method-call)
  611.                 (fast-method-call-next-method-call ,method-call)
  612.                 ,@required-args+rest-arg))
  613.  
  614. (defstruct fast-instance-boundp
  615.   (index 0 :type fixnum))
  616.  
  617. (eval-when (compile load eval)
  618. (defvar *allow-emf-call-tracing-p* nil)
  619. (defvar *enable-emf-call-tracing-p* #-testing nil #+testing t)
  620. )
  621.  
  622. (defvar *emf-call-trace-size* 200)
  623. (defvar *emf-call-trace* nil)
  624. (defvar emf-call-trace-index 0)
  625.  
  626. (defun show-emf-call-trace ()
  627.   (when *emf-call-trace*
  628.     (let ((j emf-call-trace-index)
  629.       (*enable-emf-call-tracing-p* nil))
  630.       (format t "~&(The oldest entries are printed first)~%")
  631.       (dotimes (i *emf-call-trace-size*)
  632.     (let ((ct (aref *emf-call-trace* j)))
  633.       (when ct (print ct)))
  634.     (incf j)
  635.     (when (= j *emf-call-trace-size*)
  636.       (setq j 0))))))
  637.  
  638. (defun trace-emf-call-internal (emf format args)
  639.   (unless *emf-call-trace*
  640.     (setq *emf-call-trace* (make-array *emf-call-trace-size*)))
  641.   (setf (aref *emf-call-trace* emf-call-trace-index)
  642.     (list* emf format args))
  643.   (incf emf-call-trace-index)
  644.   (when (= emf-call-trace-index *emf-call-trace-size*)
  645.     (setq emf-call-trace-index 0)))
  646.  
  647. (defmacro trace-emf-call (emf format args)
  648.   (when *allow-emf-call-tracing-p*
  649.     `(when *enable-emf-call-tracing-p*
  650.        (trace-emf-call-internal ,emf ,format ,args))))
  651.  
  652. (defmacro invoke-effective-method-function-fast
  653.     (emf restp &rest required-args+rest-arg)
  654.   `(progn
  655.      (trace-emf-call ,emf ,restp (list ,@required-args+rest-arg))
  656.      (invoke-fast-method-call ,emf ,@required-args+rest-arg)))
  657.  
  658. (defmacro invoke-effective-method-function (emf restp &rest required-args+rest-arg)
  659.   (unless (constantp restp)
  660.     (error "The restp argument to invoke-effective-method-function is not constant"))
  661.   (setq restp (eval restp))
  662.   `(progn
  663.      (trace-emf-call ,emf ,restp (list ,@required-args+rest-arg))
  664.      (cond (#-(or lucid excl) (typep ,emf 'fast-method-call)
  665.         #+(or lucid excl) (fast-method-call-p ,emf)
  666.          (invoke-fast-method-call ,emf ,@required-args+rest-arg))
  667.        ,@(when (and (null restp) (= 1 (length required-args+rest-arg)))
  668.            `(((typep ,emf 'fixnum)
  669.           (let* ((.slots. (get-slots-or-nil
  670.                    ,(car required-args+rest-arg)))
  671.              (value (when .slots. (%instance-ref .slots. ,emf))))
  672.             (if (eq value ',*slot-unbound*)
  673.             (slot-unbound-internal ,(car required-args+rest-arg)
  674.                            ,emf)
  675.             value)))))
  676.        ,@(when (and (null restp) (= 2 (length required-args+rest-arg)))
  677.            `(((typep ,emf 'fixnum)
  678.           (let ((.new-value. ,(car required-args+rest-arg))
  679.             (.slots. (get-slots-or-nil
  680.                   ,(car required-args+rest-arg))))
  681.             (when .slots. ; just to avoid compiler wranings
  682.               (setf (%instance-ref .slots. ,emf) .new-value.))))))
  683.        #|| 
  684.        ,@(when (and (null restp) (= 1 (length required-args+rest-arg)))
  685.            `(((typep ,emf 'fast-instance-boundp)
  686.           (let ((.slots. (get-slots-or-nil
  687.                   ,(car required-args+rest-arg))))
  688.             (and .slots.
  689.              (not (eq (%instance-ref
  690.                    .slots. (fast-instance-boundp-index ,emf))
  691.                   ',*slot-unbound*)))))))
  692.        ||#
  693.        (t
  694.         (etypecase ,emf
  695.           (method-call
  696.            (invoke-method-call ,emf ,restp ,@required-args+rest-arg))
  697.           (function
  698.            ,(if restp
  699.             `(apply ,emf ,@required-args+rest-arg)
  700.             `(funcall ,emf ,@required-args+rest-arg))))))))
  701.  
  702. (defun invoke-emf (emf args)
  703.   (trace-emf-call emf t args)
  704.   (etypecase emf
  705.     (fast-method-call
  706.      (let* ((arg-info (fast-method-call-arg-info emf))
  707.         (restp (cdr arg-info))
  708.         (nreq (car arg-info)))
  709.        (if restp
  710.        (let* ((rest-args (nthcdr nreq args))
  711.           (req-args (ldiff args rest-args)))
  712.          (apply (fast-method-call-function emf)
  713.             (fast-method-call-pv-cell emf)
  714.             (fast-method-call-next-method-call emf)
  715.             (nconc req-args (list rest-args))))
  716.        (cond ((null args)
  717.           (if (eql nreq 0) 
  718.               (invoke-fast-method-call emf)
  719.               (error "wrong number of args")))
  720.          ((null (cdr args))
  721.           (if (eql nreq 1) 
  722.               (invoke-fast-method-call emf (car args))
  723.               (error "wrong number of args")))
  724.          ((null (cddr args))
  725.           (if (eql nreq 2) 
  726.               (invoke-fast-method-call emf (car args) (cadr args))
  727.               (error "wrong number of args")))
  728.          (t
  729.           (apply (fast-method-call-function emf)
  730.              (fast-method-call-pv-cell emf)
  731.              (fast-method-call-next-method-call emf)
  732.              args))))))
  733.     (method-call 
  734.      (apply (method-call-function emf)
  735.         args
  736.         (method-call-call-method-args emf)))
  737.     (fixnum 
  738.      (cond ((null args) (error "1 or 2 args expected"))
  739.        ((null (cdr args))
  740.         (let ((value (%instance-ref (get-slots (car args)) emf)))
  741.           (if (eq value *slot-unbound*)
  742.           (slot-unbound-internal (car args) emf)
  743.           value)))
  744.        ((null (cddr args))
  745.         (setf (%instance-ref (get-slots (cadr args)) emf)
  746.           (car args)))
  747.        (t (error "1 or 2 args expected"))))
  748.     (fast-instance-boundp
  749.      (if (or (null args) (cdr args))
  750.      (error "1 arg expected")
  751.      (not (eq (%instance-ref (get-slots (car args)) 
  752.                  (fast-instance-boundp-index emf))
  753.           *slot-unbound*))))
  754.     (function
  755.      (apply emf args))))
  756.  
  757. ;; This can be improved alot.
  758. (defun gf-make-function-from-emf (gf emf)
  759.   (etypecase emf
  760.     (fast-method-call (let* ((arg-info (gf-arg-info gf))
  761.                  (nreq (arg-info-number-required arg-info))
  762.                  (restp (arg-info-applyp arg-info)))
  763.             #'(lambda (&rest args)
  764.                 #+copy-&rest-arg (setq args (copy-list args))
  765.                 (trace-emf-call emf t args)
  766.                 (apply (fast-method-call-function emf)
  767.                    (fast-method-call-pv-cell emf)
  768.                    (fast-method-call-next-method-call emf)
  769.                    (if restp
  770.                        (let* ((rest-args (nthcdr nreq args))
  771.                           (req-args (ldiff args rest-args)))
  772.                      (nconc req-args rest-args))
  773.                        args)))))
  774.     (method-call #'(lambda (&rest args)
  775.              #+copy-&rest-arg (setq args (copy-list args))
  776.              (trace-emf-call emf t args)
  777.              (apply (method-call-function emf)
  778.                 args
  779.                 (method-call-call-method-args emf))))
  780.     (function emf)))
  781.  
  782. (defmacro bind-fast-lexical-method-macros ((args rest-arg next-method-call)
  783.                        &body body)
  784.   `(macrolet ((call-next-method-bind (&body body)
  785.         `(let () ,@body))
  786.           (call-next-method-body (cnm-args)
  787.         `(if ,',next-method-call
  788.              ,(if (and (null ',rest-arg)
  789.                    (consp cnm-args)
  790.                    (eq (car cnm-args) 'list))
  791.               `(invoke-effective-method-function
  792.                 ,',next-method-call nil
  793.                 ,@(cdr cnm-args))
  794.               (let ((call `(invoke-effective-method-function
  795.                     ,',next-method-call 
  796.                     ,',(not (null rest-arg))
  797.                     ,@',args 
  798.                     ,@',(when rest-arg `(,rest-arg)))))
  799.                 `(if ,cnm-args
  800.                  (bind-args ((,@',args ,@',(when rest-arg
  801.                                  `(&rest ,rest-arg)))
  802.                          ,cnm-args)
  803.                         ,call)
  804.                  ,call)))
  805.              (error "No next method.")))
  806.           (next-method-p-body ()
  807.             `(not (null ,',next-method-call))))
  808.      ,@body))
  809.  
  810. (defmacro bind-lexical-method-functions 
  811.     ((&key call-next-method-p next-method-p-p closurep applyp)
  812.      &body body)
  813.   (cond ((and (null call-next-method-p) (null next-method-p-p)
  814.           (null closurep)
  815.           (null applyp))
  816.      `(let () ,@body))
  817.      ((and (null closurep)
  818.            (null applyp))
  819.      ;; OK to use MACROLET, and all args are mandatory 
  820.      ;; (else APPLYP would be true).
  821.      `(call-next-method-bind
  822.         (macrolet ((call-next-method (&rest cnm-args)
  823.              `(call-next-method-body ,(when cnm-args `(list ,@cnm-args))))
  824.                (next-method-p ()
  825.              `(next-method-p-body)))
  826.            ,@body)))
  827.     (t
  828.      `(call-next-method-bind
  829.         (flet (,@(and call-next-method-p
  830.                '((call-next-method (&rest cnm-args)
  831.               #+Genera
  832.               (declare (dbg:invisible-frame :clos-internal))
  833.               #+copy-&rest-arg (setq args (copy-list args))
  834.               (call-next-method-body cnm-args))))
  835.              ,@(and next-method-p-p
  836.              '((next-method-p ()
  837.                 (next-method-p-body)))))
  838.           ,@body)))))
  839.  
  840. (defmacro bind-args ((lambda-list args) &body body)
  841.   #|| ; Lucid and Allegro don't compile the function inline
  842.   `(apply #'(lambda ,lambda-list ,@body) ,args)
  843.   ||#
  844.   (let ((args-tail '.args-tail.)
  845.     (key '.key.)
  846.     (state 'required))
  847.     (flet ((process-var (var)
  848.          (if (memq var lambda-list-keywords)
  849.          (progn
  850.            (case var
  851.              (&optional         (setq state 'optional))
  852.              (&key              (setq state 'key))
  853.              (&allow-other-keys)
  854.              (&rest             (setq state 'rest))
  855.              (&aux              (setq state 'aux))
  856.              (otherwise
  857.               (error "Encountered the non-standard lambda list keyword ~S."
  858.                  var)))
  859.            nil)
  860.          (case state
  861.            (required `((,var (pop ,args-tail))))
  862.            (optional (cond ((not (consp var))
  863.                     `((,var (when ,args-tail (pop ,args-tail)))))
  864.                    ((null (cddr var))
  865.                     `((,(car var) (if ,args-tail
  866.                               (pop ,args-tail)
  867.                               ,(cadr var)))))
  868.                    (t
  869.                     `((,(caddr var) ,args-tail)
  870.                       (,(car var) (if ,args-tail
  871.                               (pop ,args-tail)
  872.                               ,(cadr var)))))))
  873.            (rest `((,var ,args-tail)))
  874.            (key (cond ((not (consp var))
  875.                    `((,var (get-key-arg ,(make-keyword var)
  876.                                 ,args-tail))))
  877.                   ((null (cddr var))
  878.                    (multiple-value-bind (keyword variable)
  879.                    (if (consp (car var))
  880.                        (values (caar var) (cadar var))
  881.                        (values (make-keyword (car var)) (car var)))
  882.                  `((,key (get-key-arg1 ,keyword ,args-tail))
  883.                    (,variable (if (consp ,key)
  884.                           (car ,key)
  885.                           ,(cadr var))))))
  886.                   (t
  887.                    (multiple-value-bind (keyword variable)
  888.                    (if (consp (car var))
  889.                        (values (caar var) (cadar var))
  890.                        (values (make-keyword (car var)) (car var)))
  891.                  `((,key (get-key-arg1 ,keyword ,args-tail))
  892.                    (,(caddr var) ,key)
  893.                    (,variable (if (consp ,key)
  894.                           (car ,key)
  895.                           ,(cadr var))))))))
  896.            (aux `(,var))))))
  897.       (let ((bindings (mapcan #'process-var lambda-list)))
  898.     `(let* ((,args-tail ,args)
  899.         ,@bindings)
  900.        ,@(unless bindings `((declare (ignore ,args-tail))))
  901.        ,@body)))))
  902.  
  903. (defun get-key-arg (keyword list)
  904.   (loop (when (atom list) (return nil))
  905.     (when (eq (car list) keyword) (return (cadr list)))
  906.     (setq list (cddr list))))
  907.  
  908. (defun get-key-arg1 (keyword list)
  909.   (loop (when (atom list) (return nil))
  910.     (when (eq (car list) keyword) (return (cdr list)))
  911.     (setq list (cddr list))))
  912.  
  913. (defun walk-method-lambda (method-lambda required-parameters env slots calls)
  914.   (let ((call-next-method-p nil)   ;flag indicating that call-next-method
  915.                    ;should be in the method definition
  916.     (closurep nil)           ;flag indicating that #'call-next-method
  917.                    ;was seen in the body of a method
  918.     (next-method-p-p nil))     ;flag indicating that next-method-p
  919.                    ;should be in the method definition
  920.     (flet ((walk-function (form context env)
  921.          (cond ((not (eq context ':eval)) form)
  922.            ((not (listp form)) form)
  923.            ((eq (car form) 'call-next-method)
  924.             (setq call-next-method-p 't)
  925.             form)
  926.            ((eq (car form) 'next-method-p)
  927.             (setq next-method-p-p 't)
  928.             form)
  929.            ((and (eq (car form) 'function)
  930.              (cond ((eq (cadr form) 'call-next-method)
  931.                 (setq call-next-method-p 't)
  932.                 (setq closurep t)
  933.                 form)
  934.                    ((eq (cadr form) 'next-method-p)
  935.                 (setq next-method-p-p 't)
  936.                 (setq closurep t)
  937.                 form)
  938.                    (t nil))))
  939.            ((and (or (eq (car form) 'slot-value)
  940.                  (eq (car form) 'set-slot-value)
  941.                  (eq (car form) 'slot-boundp))
  942.              (constantp (caddr form)))
  943.             (let ((parameter
  944.                (can-optimize-access form
  945.                         required-parameters env)))
  946.               (ecase (car form)
  947.             (slot-value
  948.              (optimize-slot-value     slots parameter form))
  949.             (set-slot-value
  950.              (optimize-set-slot-value slots parameter form))
  951.             (slot-boundp
  952.              (optimize-slot-boundp    slots parameter form)))))
  953.            ((and (eq (car form) 'apply)
  954.              (consp (cadr form))
  955.              (eq (car (cadr form)) 'function)
  956.              (generic-function-name-p (cadr (cadr form))))
  957.             (optimize-generic-function-call 
  958.              form required-parameters env slots calls))
  959.            ((and (or (symbolp (car form))
  960.                  (and (consp (car form))
  961.                   (eq (caar form) 'setf)))
  962.              (generic-function-name-p (car form)))
  963.             (optimize-generic-function-call 
  964.              form required-parameters env slots calls))
  965.            ((and (eq (car form) 'asv-funcall)
  966.              *optimize-asv-funcall-p*)
  967.             (case (fourth form)
  968.               (reader (push (third form) *asv-readers*))
  969.               (writer (push (third form) *asv-writers*))
  970.               (boundp (push (third form) *asv-boundps*)))
  971.             `(,(second form) ,@(cddddr form)))
  972.            (t form))))
  973.       
  974.       (let ((walked-lambda (walk-form method-lambda env #'walk-function)))
  975.     (values walked-lambda
  976.         call-next-method-p closurep next-method-p-p)))))
  977.  
  978. (defun generic-function-name-p (name)
  979.   (and (or (symbolp name)
  980.        (and (consp name)
  981.         (eq (car name) 'setf)
  982.         (consp (cdr name))
  983.         (symbolp (cadr name))
  984.         (null (cddr name))))
  985.        (gboundp name)
  986.        (if (eq *boot-state* 'complete)
  987.        (standard-generic-function-p (gdefinition name))
  988.        (funcallable-instance-p (gdefinition name)))))
  989.  
  990. (defun make-parameter-references (specialized-lambda-list
  991.                   required-parameters
  992.                   declarations
  993.                   method-name
  994.                   specializers)
  995.   (flet ((ignoredp (symbol)
  996.        (dolist (decl (cdar declarations))
  997.          (when (and (eq (car decl) 'ignore)
  998.             (memq symbol (cdr decl)))
  999.            (return t)))))       
  1000.     (gathering ((references (collecting)))
  1001.       (iterate ((s (list-elements specialized-lambda-list))
  1002.         (p (list-elements required-parameters)))
  1003.     (progn p)
  1004.     (cond ((not (listp s)))
  1005.           ((ignoredp (car s))
  1006.            (warn "In defmethod ~S, there is a~%~
  1007.                       redundant ignore declaration for the parameter ~S."
  1008.              method-name
  1009.              specializers
  1010.              (car s)))
  1011.           (t
  1012.            (gather (car s) references)))))))
  1013.  
  1014.  
  1015. (defvar *method-function-plist* (make-hash-table :test #'eq))
  1016. (defvar *mf1* nil) (defvar *mf1p* nil) (defvar *mf1cp* nil)
  1017. (defvar *mf2* nil) (defvar *mf2p* nil) (defvar *mf2cp* nil)
  1018.  
  1019. (defun method-function-plist (method-function)
  1020.   (unless (eq method-function *mf1*)
  1021.     (rotatef *mf1* *mf2*)
  1022.     (rotatef *mf1p* *mf2p*)
  1023.     (rotatef *mf1cp* *mf2cp*))
  1024.   (unless (or (eq method-function *mf1*) (null *mf1cp*))
  1025.     (setf (gethash *mf1* *method-function-plist*) *mf1p*))
  1026.   (unless (eq method-function *mf1*)
  1027.     (setf *mf1* method-function
  1028.       *mf1cp* nil
  1029.       *mf1p* (gethash method-function *method-function-plist*)))
  1030.   *mf1p*)
  1031.  
  1032. (defun #-setf SETF\ PCL\ METHOD-FUNCTION-PLIST #+setf (setf method-function-plist)
  1033.        (val method-function)
  1034.   (unless (eq method-function *mf1*)
  1035.     (rotatef *mf1* *mf2*)
  1036.     (rotatef *mf1cp* *mf2cp*)
  1037.     (rotatef *mf1p* *mf2p*))
  1038.   (unless (or (eq method-function *mf1*) (null *mf1cp*))
  1039.     (setf (gethash *mf1* *method-function-plist*) *mf1p*))
  1040.   (setf *mf1* method-function
  1041.     *mf1cp* t
  1042.     *mf1p* val))
  1043.  
  1044. (defun method-function-get (method-function key &optional default)
  1045.   (getf (method-function-plist method-function) key default))
  1046.  
  1047. (defun #-setf SETF\ PCL\ METHOD-FUNCTION-GET #+setf (setf method-function-get)
  1048.        (val method-function key)
  1049.   (setf (getf (method-function-plist method-function) key) val))
  1050.  
  1051.  
  1052. (defun method-function-pv-table (method-function)
  1053.   (method-function-get method-function :pv-table))
  1054.  
  1055. (defun method-function-method (method-function)
  1056.   (method-function-get method-function :method))
  1057.  
  1058. (defun method-function-needs-next-methods-p (method-function)
  1059.   (method-function-get method-function :needs-next-methods-p t))
  1060.  
  1061.  
  1062.  
  1063. (defmacro method-function-closure-generator (method-function)
  1064.   `(method-function-get ,method-function 'closure-generator))
  1065.  
  1066. (defun load-defmethod (class name quals specls ll initargs &optional pv-table-symbol)
  1067.   (when (listp name) (do-standard-defsetf-1 (cadr name)))
  1068.   (setq initargs (copy-tree initargs))
  1069.   (let ((method-spec (or (getf initargs ':method-spec)
  1070.              (make-method-spec name quals specls))))
  1071.     (setf (getf initargs ':method-spec) method-spec)
  1072.     (record-definition 'method method-spec)
  1073.     (load-defmethod-internal class name quals specls ll initargs pv-table-symbol)))
  1074.  
  1075. (defun load-defmethod-internal
  1076.     (method-class gf-spec qualifiers specializers lambda-list 
  1077.           initargs pv-table-symbol)
  1078.   (when (listp gf-spec) (do-standard-defsetf-1 (cadr gf-spec)))
  1079.   (when pv-table-symbol
  1080.     (setf (getf (getf initargs ':plist) :pv-table-symbol)
  1081.       pv-table-symbol))
  1082.   (let ((method (apply #'add-named-method
  1083.                gf-spec qualifiers specializers lambda-list
  1084.                :definition-source `((defmethod ,gf-spec
  1085.                         ,@qualifiers
  1086.                           ,specializers)
  1087.                         ,(load-truename))
  1088.                initargs)))
  1089.     (unless (or (eq method-class 'standard-method)
  1090.         (eq (find-class method-class nil) (class-of method)))
  1091.       (format *error-output*
  1092.           "~&At the time the method with qualifiers ~:S and~%~
  1093.                specializers ~:S on the generic function ~S~%~
  1094.                was compiled, the method-class for that generic function was~%~
  1095.                ~S.  But, the method class is now ~S, this~%~
  1096.                may mean that this method was compiled improperly.~%"
  1097.           qualifiers specializers gf-spec
  1098.           method-class (class-name (class-of method))))
  1099.     method))
  1100.  
  1101. (defun make-method-spec (gf-spec qualifiers unparsed-specializers)
  1102.   `(method ,gf-spec ,@qualifiers ,unparsed-specializers))
  1103.  
  1104. (defun initialize-method-function (initargs &optional return-function-p method)
  1105.   (let* ((mf (getf initargs ':function))
  1106.      (method-spec (getf initargs ':method-spec))
  1107.      (plist (getf initargs ':plist))
  1108.      (pv-table-symbol (getf plist ':pv-table-symbol))
  1109.      (pv-table nil)
  1110.      (mff (getf initargs ':fast-function)))
  1111.     (flet ((set-mf-property (p v)
  1112.          (when mf
  1113.            (setf (method-function-get mf p) v))
  1114.          (when mff
  1115.            (setf (method-function-get mff p) v))))
  1116.       (when method-spec
  1117.     (when mf
  1118.       (setq mf (set-function-name mf method-spec)))
  1119.     (when mff
  1120.       (let ((name `(,(or (get (car method-spec) 'fast-sym)
  1121.                  (setf (get (car method-spec) 'fast-sym)
  1122.                    (intern (format nil "FAST-~A"
  1123.                            (car method-spec))
  1124.                        *the-pcl-package*)))
  1125.              ,@(cdr method-spec))))
  1126.         (set-function-name mff name)
  1127.         (unless mf
  1128.           (set-mf-property :name name)))))
  1129.       (when plist
  1130.     (let ((snl (getf plist :slot-name-lists))
  1131.           (cl (getf plist :call-list)))
  1132.       (when (or snl cl)
  1133.         (setq pv-table (intern-pv-table :slot-name-lists snl
  1134.                         :call-list cl))
  1135.         (when pv-table (set pv-table-symbol pv-table))
  1136.         (set-mf-property :pv-table pv-table)))    
  1137.     (loop (when (null plist) (return nil))
  1138.           (set-mf-property (pop plist) (pop plist)))      
  1139.     (when method
  1140.       (set-mf-property :method method))    
  1141.     (when return-function-p
  1142.       (or mf (method-function-from-fast-function mff)))))))
  1143.  
  1144.  
  1145.  
  1146. (defun analyze-lambda-list (lambda-list)
  1147.   ;;(declare (values nrequired noptional keysp restp allow-other-keys-p
  1148.   ;;                 keywords keyword-parameters))
  1149.   (flet ((parse-keyword-argument (arg)
  1150.        (if (listp arg)
  1151.            (if (listp (car arg))
  1152.            (caar arg)
  1153.            (make-keyword (car arg)))
  1154.            (make-keyword arg))))
  1155.     (let ((nrequired 0)
  1156.       (noptional 0)
  1157.       (keysp nil)
  1158.       (restp nil)
  1159.       (allow-other-keys-p nil)
  1160.       (keywords ())
  1161.       (keyword-parameters ())
  1162.       (state 'required))
  1163.       (dolist (x lambda-list)
  1164.     (if (memq x lambda-list-keywords)
  1165.         (case x
  1166.           (&optional         (setq state 'optional))
  1167.           (&key              (setq keysp 't
  1168.                        state 'key))
  1169.           (&allow-other-keys (setq allow-other-keys-p 't))
  1170.           (&rest             (setq restp 't
  1171.                        state 'rest))
  1172.           (&aux              (return t))
  1173.           (otherwise
  1174.         (error "Encountered the non-standard lambda list keyword ~S." x)))
  1175.         (ecase state
  1176.           (required  (incf nrequired))
  1177.           (optional  (incf noptional))
  1178.           (key       (push (parse-keyword-argument x) keywords)
  1179.              (push x keyword-parameters))
  1180.           (rest      ()))))
  1181.       (values nrequired noptional keysp restp allow-other-keys-p
  1182.           (reverse keywords)
  1183.           (reverse keyword-parameters)))))
  1184.  
  1185. (defun keyword-spec-name (x)
  1186.   (let ((key (if (atom x) x (car x))))
  1187.     (if (atom key)
  1188.     (intern (symbol-name key) (find-package "KEYWORD"))
  1189.     (car key))))
  1190.  
  1191. (defun ftype-declaration-from-lambda-list (lambda-list #+cmu name)
  1192.   (multiple-value-bind (nrequired noptional keysp restp allow-other-keys-p
  1193.                   keywords keyword-parameters)
  1194.       (analyze-lambda-list lambda-list)
  1195.     (declare (ignore keyword-parameters))
  1196.     (let* (#+cmu (old (c::info function type name))
  1197.        #+cmu (old-ftype (if (c::function-type-p old) old nil))
  1198.        #+cmu (old-restp (and old-ftype (c::function-type-rest old-ftype)))
  1199.        #+cmu (old-keys (and old-ftype
  1200.                 (mapcar #'c::key-info-name
  1201.                     (c::function-type-keywords old-ftype))))
  1202.        #+cmu (old-keysp (and old-ftype (c::function-type-keyp old-ftype)))
  1203.        #+cmu (old-allowp (and old-ftype (c::function-type-allowp old-ftype)))
  1204.        (keywords #+cmu (union old-keys (mapcar #'keyword-spec-name keywords))
  1205.              #-cmu (mapcar #'keyword-spec-name keywords)))
  1206.       `(function ,(append (make-list nrequired :initial-element 't)
  1207.               (when (plusp noptional)
  1208.                 (append '(&optional)
  1209.                     (make-list noptional :initial-element 't)))
  1210.               (when (or restp #+cmu old-restp)
  1211.                 '(&rest t))
  1212.               (when (or keysp #+cmu old-keysp)
  1213.                 (append '(&key)
  1214.                     (mapcar #'(lambda (key)
  1215.                         `(,key t))
  1216.                         keywords)
  1217.                     (when (or allow-other-keys-p #+cmu old-allowp)
  1218.                       '(&allow-other-keys)))))
  1219.          *))))
  1220.  
  1221. (defun proclaim-defgeneric (spec lambda-list)
  1222.   #-cmu (declare (ignore lambda-list))
  1223.   (when (consp spec)
  1224.     (setq spec (get-setf-function-name (cadr spec))))
  1225.   (let (#+cmu
  1226.     (decl `(ftype ,(ftype-declaration-from-lambda-list lambda-list #+cmu spec)
  1227.               ,spec)))
  1228.     #+cmu (proclaim decl)
  1229.     #+kcl (setf (get spec 'compiler::proclaimed-closure) t)))
  1230.  
  1231. ;;;; Early generic-function support
  1232. ;;;
  1233. ;;;
  1234. (defvar *early-generic-functions* ())
  1235.  
  1236. (defun ensure-generic-function (function-specifier
  1237.                 &rest all-keys
  1238.                 &key environment
  1239.                 &allow-other-keys)
  1240.   (declare (ignore environment))
  1241.   #+copy-&rest-arg (setq all-keys (copy-list all-keys))
  1242.   (let ((existing (and (gboundp function-specifier)               
  1243.                (gdefinition function-specifier))))
  1244.     (if (and existing
  1245.          (eq *boot-state* 'complete)
  1246.          (null (generic-function-p existing)))
  1247.     (generic-clobbers-function function-specifier)
  1248.     (apply #'ensure-generic-function-using-class
  1249.            existing function-specifier all-keys))))
  1250.  
  1251. (defun generic-clobbers-function (function-specifier)
  1252.   #+Lispm (zl:signal 'generic-clobbers-function :name function-specifier)
  1253.   #-Lispm (error "~S already names an ordinary function or a macro,~%~
  1254.                   you may want to replace it with a generic function, but doing so~%~
  1255.                   will require that you decide what to do with the existing function~%~
  1256.                   definition.~%~
  1257.                   The PCL-specific function MAKE-SPECIALIZABLE may be useful to you."
  1258.          function-specifier))
  1259.  
  1260. #+Lispm
  1261. (zl:defflavor generic-clobbers-function (name) (si:error)
  1262.   :initable-instance-variables)
  1263.  
  1264. #+Lispm
  1265. (zl:defmethod #+Genera (dbg:report generic-clobbers-function)
  1266.           #+ti (generic-clobbers-function :report)
  1267.           (stream)
  1268.  (format stream
  1269.      "~S aready names a ~a"
  1270.      name
  1271.      (if (and (symbolp name) (macro-function name)) "macro" "function")))
  1272.  
  1273. #+Genera
  1274. (zl:defmethod (sys:proceed generic-clobbers-function :specialize-it) ()
  1275.   "Make it specializable anyway?"
  1276.   (make-specializable name))
  1277.  
  1278. #+ti
  1279. (zl:defmethod
  1280.      (generic-clobbers-function :case :proceed-asking-user :specialize-it)
  1281.      (continuation ignore)
  1282.   "Make it specializable anyway?"
  1283.   (make-specializable name)
  1284.   (funcall continuation :specialize-it))
  1285.  
  1286. (defvar *sgf-wrapper* 
  1287.   (make-wrapper (early-class-size 'standard-generic-function)))
  1288.  
  1289. (defvar *sgf-slots-init*
  1290.   (mapcar #'(lambda (canonical-slot)
  1291.           (if (memq (getf canonical-slot :name) '(arg-info source))
  1292.           *slot-unbound*
  1293.           (let ((initfunction (getf canonical-slot :initfunction)))
  1294.             (if initfunction
  1295.             (funcall initfunction)
  1296.             *slot-unbound*))))
  1297.       (early-collect-inheritance 'standard-generic-function)))
  1298.  
  1299. (defvar *sgf-method-class-index* 
  1300.   (bootstrap-slot-index 'standard-generic-function 'method-class))
  1301.  
  1302. (defun early-gf-p (x)
  1303.   (and (fsc-instance-p x)
  1304.        (eq (instance-ref (get-slots x) *sgf-method-class-index*)
  1305.        *slot-unbound*)))
  1306.  
  1307. (defvar *sgf-methods-index* 
  1308.   (bootstrap-slot-index 'standard-generic-function 'methods))
  1309.  
  1310. (defmacro early-gf-methods (gf)
  1311.   `(instance-ref (get-slots ,gf) *sgf-methods-index*))
  1312.  
  1313. (defvar *sgf-arg-info-index* 
  1314.   (bootstrap-slot-index 'standard-generic-function 'arg-info))
  1315.  
  1316. (defmacro early-gf-arg-info (gf)
  1317.   `(instance-ref (get-slots ,gf) *sgf-arg-info-index*))
  1318.  
  1319. (defvar *sgf-dfun-state-index* 
  1320.   (bootstrap-slot-index 'standard-generic-function 'dfun-state))
  1321.  
  1322. (defstruct (arg-info
  1323.          (:conc-name nil)
  1324.          (:constructor make-arg-info ()))
  1325.   (arg-info-lambda-list :no-lambda-list)
  1326.   arg-info-precedence
  1327.   arg-info-metatypes
  1328.   arg-info-number-optional
  1329.   arg-info-key/rest-p
  1330.   arg-info-keywords ;nil         no keyword or rest allowed
  1331.                 ;(k1 k2 ..)  each method must accept these keyword arguments
  1332.                 ;T           must have &key or &rest
  1333.  
  1334.   gf-info-simple-accessor-type ; nil, reader, writer, boundp
  1335.   (gf-precompute-dfun-and-emf-p nil) ; set by set-arg-info
  1336.  
  1337.   gf-info-static-c-a-m-emf
  1338.   (gf-info-c-a-m-emf-std-p t)
  1339.   gf-info-fast-mf-p)
  1340.  
  1341. (defun arg-info-valid-p (arg-info)
  1342.   (not (null (arg-info-number-optional arg-info))))
  1343.  
  1344. (defun arg-info-applyp (arg-info)
  1345.   (or (plusp (arg-info-number-optional arg-info))
  1346.       (arg-info-key/rest-p arg-info)))
  1347.  
  1348. (defun arg-info-number-required (arg-info)
  1349.   (length (arg-info-metatypes arg-info)))
  1350.  
  1351. (defun arg-info-nkeys (arg-info)
  1352.   (count-if #'(lambda (x) (neq x 't)) (arg-info-metatypes arg-info)))
  1353.  
  1354. (defun set-arg-info (gf &key new-method (lambda-list nil lambda-list-p)
  1355.             argument-precedence-order)
  1356.   (let* ((arg-info (if (eq *boot-state* 'complete)
  1357.                (gf-arg-info gf)
  1358.                (early-gf-arg-info gf)))
  1359.      (methods (if (eq *boot-state* 'complete)
  1360.               (generic-function-methods gf)
  1361.               (early-gf-methods gf)))
  1362.      (was-valid-p (integerp (arg-info-number-optional arg-info)))
  1363.      (first-p (and new-method (null (cdr methods)))))
  1364.     (when (and (not lambda-list-p) methods)      
  1365.       (setq lambda-list (gf-lambda-list gf)))
  1366.     (when (or lambda-list-p
  1367.           (and first-p (eq (arg-info-lambda-list arg-info) ':no-lambda-list)))
  1368.       (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p keywords)
  1369.       (analyze-lambda-list lambda-list)
  1370.     (when (and methods (not first-p))
  1371.       (let ((gf-nreq (arg-info-number-required arg-info))
  1372.         (gf-nopt (arg-info-number-optional arg-info))
  1373.         (gf-key/rest-p (arg-info-key/rest-p arg-info)))
  1374.         (unless (and (= nreq gf-nreq)
  1375.              (= nopt gf-nopt)
  1376.              (eq (or keysp restp) gf-key/rest-p))
  1377.           (error "The lambda-list ~S is incompatible with ~
  1378.                      existing methods of ~S."
  1379.              lambda-list gf))))
  1380.     (when lambda-list-p
  1381.       (setf (arg-info-lambda-list arg-info) lambda-list))
  1382.     (when (or lambda-list-p argument-precedence-order
  1383.           (null (arg-info-precedence arg-info)))
  1384.       (setf (arg-info-precedence arg-info)
  1385.         (compute-precedence lambda-list nreq argument-precedence-order)))
  1386.     (setf (arg-info-metatypes arg-info) (make-list nreq))
  1387.     (setf (arg-info-number-optional arg-info) nopt)
  1388.     (setf (arg-info-key/rest-p arg-info) (not (null (or keysp restp))))
  1389.     (setf (arg-info-keywords arg-info) 
  1390.           (if lambda-list-p
  1391.           (if allow-other-keys-p t keywords)
  1392.           (arg-info-key/rest-p arg-info)))))
  1393.     (when new-method
  1394.       (check-method-arg-info gf arg-info new-method))
  1395.     (set-arg-info1 gf arg-info new-method methods was-valid-p first-p)
  1396.     arg-info))
  1397.  
  1398. (defun check-method-arg-info (gf arg-info method)
  1399.   (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p keywords)
  1400.       (analyze-lambda-list (if (consp method)
  1401.                    (early-method-lambda-list method)
  1402.                    (method-lambda-list method)))
  1403.     (flet ((lose (string &rest args)
  1404.          (error "Attempt to add the method ~S to the generic function ~S.~%~
  1405.                    But ~A" method gf (apply #'format nil string args)))
  1406.        (compare (x y)
  1407.          (if (> x y) "more" "fewer")))
  1408.       (let ((gf-nreq (arg-info-number-required arg-info))
  1409.         (gf-nopt (arg-info-number-optional arg-info))
  1410.         (gf-key/rest-p (arg-info-key/rest-p arg-info))
  1411.         (gf-keywords (arg-info-keywords arg-info)))
  1412.     (unless (= nreq gf-nreq)
  1413.       (lose "the method has ~A required arguments than the generic function."
  1414.         (compare nreq gf-nreq)))
  1415.     (unless (= nopt gf-nopt)
  1416.       (lose "the method has ~S optional arguments than the generic function."
  1417.         (compare nopt gf-nopt)))
  1418.     (unless (eq (or keysp restp) gf-key/rest-p)
  1419.       (error "the method and generic function differ in whether they accept~%~
  1420.                   rest or keyword arguments."))
  1421.     (when (consp gf-keywords)
  1422.       (unless (or (and restp (not keysp))
  1423.               allow-other-keys-p
  1424.               (every #'(lambda (k) (memq k keywords)) gf-keywords))
  1425.         (lose "the method does not accept each of the keyword arguments~%~
  1426.                  ~S." gf-keywords)))))))
  1427.  
  1428. (defun set-arg-info1 (gf arg-info new-method methods was-valid-p first-p)  
  1429.   (let* ((existing-p (and methods (cdr methods) new-method))
  1430.      (nreq (length (arg-info-metatypes arg-info)))
  1431.      (metatypes (if existing-p
  1432.             (arg-info-metatypes arg-info)
  1433.             (make-list nreq)))
  1434.      (type (if existing-p
  1435.            (gf-info-simple-accessor-type arg-info)
  1436.            nil)))
  1437.     (when (arg-info-valid-p arg-info)
  1438.       (dolist (method (if new-method (list new-method) methods))
  1439.     (let* ((specializers (if (or (eq *boot-state* 'complete)
  1440.                      (not (consp method)))
  1441.                  (method-specializers method)
  1442.                  (early-method-specializers method t)))
  1443.            (class (if (or (eq *boot-state* 'complete) (not (consp method)))
  1444.               (class-of method)
  1445.               (early-method-class method)))
  1446.            (new-type (when (and class
  1447.                     (or (not (eq *boot-state* 'complete))
  1448.                     (eq (generic-function-method-combination gf)
  1449.                         *standard-method-combination*)))
  1450.                (cond ((eq class *the-class-standard-reader-method*)
  1451.                   'reader)
  1452.                  ((eq class *the-class-standard-writer-method*)
  1453.                   'writer)
  1454.                  ((eq class *the-class-standard-boundp-method*)
  1455.                   'boundp)))))
  1456.       (setq metatypes (mapcar #'raise-metatype metatypes specializers))
  1457.       (setq type (cond ((null type) new-type)
  1458.                ((eq type new-type) type)
  1459.                (t nil)))))
  1460.       (setf (arg-info-metatypes arg-info) metatypes)
  1461.       (setf (gf-info-simple-accessor-type arg-info) type)))
  1462.   (when (or (not was-valid-p) first-p)
  1463.     (multiple-value-bind (c-a-m-emf std-p)
  1464.     (if (early-gf-p gf)
  1465.         (values t t)
  1466.         (compute-applicable-methods-emf gf))
  1467.       (setf (gf-info-static-c-a-m-emf arg-info) c-a-m-emf)
  1468.       (setf (gf-info-c-a-m-emf-std-p arg-info) std-p)
  1469.       (unless (gf-info-c-a-m-emf-std-p arg-info)
  1470.     (setf (gf-info-simple-accessor-type arg-info) t))))
  1471.   (unless was-valid-p
  1472.     (let ((name (if (eq *boot-state* 'complete)
  1473.             (generic-function-name gf)
  1474.             (early-gf-name gf))))
  1475.       (setf (gf-precompute-dfun-and-emf-p arg-info) 
  1476.         (let* ((sym (if (atom name) name (cadr name)))
  1477.            (pkg-list (cons *the-pcl-package* 
  1478.                    (package-use-list *the-pcl-package*))))
  1479.           (and sym (symbolp sym)
  1480.            (not (null (memq (symbol-package sym) pkg-list)))
  1481.            (not (find #\space (symbol-name sym))))))))
  1482.   (setf (gf-info-fast-mf-p arg-info)
  1483.     (or (not (eq *boot-state* 'complete))
  1484.         (let* ((method-class (generic-function-method-class gf))
  1485.            (methods (compute-applicable-methods 
  1486.                  #'make-method-lambda
  1487.                  (list gf (class-prototype method-class)
  1488.                    '(lambda) nil))))
  1489.           (and methods (null (cdr methods))
  1490.            (let ((specls (method-specializers (car methods))))
  1491.              (and (classp (car specls))
  1492.               (eq 'standard-generic-function (class-name (car specls)))
  1493.               (classp (cadr specls))
  1494.               (eq 'standard-method (class-name (cadr specls)))))))))
  1495.   arg-info)
  1496.  
  1497. ;;;
  1498. ;;; This is the early definition of ensure-generic-function-using-class.
  1499. ;;; 
  1500. ;;; The static-slots field of the funcallable instances used as early generic
  1501. ;;; functions is used to store the early methods and early discriminator code
  1502. ;;; for the early generic function.  The static slots field of the fins
  1503. ;;; contains a list whose:
  1504. ;;;    CAR    -   a list of the early methods on this early gf
  1505. ;;;    CADR   -   the early discriminator code for this method
  1506. ;;;    
  1507. (defun ensure-generic-function-using-class (existing spec &rest keys
  1508.                         &key (lambda-list nil lambda-list-p)
  1509.                         &allow-other-keys)
  1510.   (declare (ignore keys))
  1511.   (cond ((and existing (early-gf-p existing))
  1512.      existing)
  1513.     ((assoc spec *generic-function-fixups* :test #'equal)
  1514.      (if existing
  1515.          (make-early-gf spec lambda-list lambda-list-p existing)           
  1516.          (error "The function ~S is not already defined" spec)))
  1517.     (existing
  1518.      (error "~S should be on the list ~S" spec '*generic-function-fixups*))
  1519.     (t
  1520.      (pushnew spec *early-generic-functions* :test #'equal)
  1521.      (make-early-gf spec lambda-list lambda-list-p))))
  1522.  
  1523. (defun make-early-gf (spec &optional lambda-list lambda-list-p function)
  1524.   (let ((fin (allocate-funcallable-instance *sgf-wrapper* *sgf-slots-init*)))
  1525.     (set-funcallable-instance-function 
  1526.      fin 
  1527.      (or function
  1528.      (if (eq spec 'print-object)
  1529.          #'(lambda (instance stream)
  1530.          (printing-random-thing (instance stream)
  1531.            (format stream "std-instance")))
  1532.          #'(lambda (&rest args)
  1533.          (declare (ignore args))
  1534.          (error "The function of the funcallable-instance ~S~
  1535.                          has not been set" fin)))))
  1536.     (setf (gdefinition spec) fin)
  1537.     (bootstrap-set-slot 'standard-generic-function fin 'name spec)
  1538.     (bootstrap-set-slot 'standard-generic-function fin 'source (load-truename))
  1539.     (set-function-name fin spec)
  1540.     (let ((arg-info (make-arg-info)))
  1541.       (setf (early-gf-arg-info fin) arg-info)
  1542.       (when lambda-list-p
  1543.     (proclaim-defgeneric spec lambda-list)
  1544.     (set-arg-info fin :lambda-list lambda-list)))
  1545.     fin))
  1546.  
  1547. (defun set-dfun (gf &optional dfun cache info)
  1548.   (when cache
  1549.     (setf (cache-owner cache) gf))
  1550.   (let ((new-state (if (and dfun (or cache info))
  1551.                (list* dfun cache info)
  1552.                dfun)))
  1553.     (if (eq *boot-state* 'complete)
  1554.     (setf (gf-dfun-state gf) new-state)
  1555.     (setf (instance-ref (get-slots gf) *sgf-dfun-state-index*) new-state)))
  1556.   dfun)
  1557.  
  1558. (defun gf-dfun-cache (gf)
  1559.   (let ((state (if (eq *boot-state* 'complete)
  1560.            (gf-dfun-state gf)
  1561.            (instance-ref (get-slots gf) *sgf-dfun-state-index*))))
  1562.     (typecase state
  1563.       (function nil)
  1564.       (cons (cadr state)))))
  1565.  
  1566. (defun gf-dfun-info (gf)
  1567.   (let ((state (if (eq *boot-state* 'complete)
  1568.            (gf-dfun-state gf)
  1569.            (instance-ref (get-slots gf) *sgf-dfun-state-index*))))
  1570.     (typecase state
  1571.       (function nil)
  1572.       (cons (cddr state)))))
  1573.  
  1574. (defvar *sgf-name-index* 
  1575.   (bootstrap-slot-index 'standard-generic-function 'name))
  1576.  
  1577. (defun early-gf-name (gf)
  1578.   (instance-ref (get-slots gf) *sgf-name-index*))
  1579.  
  1580. (defun gf-lambda-list (gf)
  1581.   (let ((arg-info (if (eq *boot-state* 'complete)
  1582.               (gf-arg-info gf)
  1583.               (early-gf-arg-info gf))))
  1584.     (if (eq ':no-lambda-list (arg-info-lambda-list arg-info))
  1585.     (let ((methods (if (eq *boot-state* 'complete)
  1586.                (generic-function-methods gf)
  1587.                (early-gf-methods gf))))
  1588.       (if (null methods)
  1589.           (progn
  1590.         (warn "No way to determine the lambda list for ~S." gf)
  1591.         nil)
  1592.           (let* ((method (car (last methods)))
  1593.              (ll (if (consp method)
  1594.                  (early-method-lambda-list method)
  1595.                  (method-lambda-list method)))
  1596.              (k (member '&key ll)))
  1597.         (if k 
  1598.             (append (ldiff ll (cdr k)) '(&allow-other-keys))
  1599.             ll))))
  1600.     (arg-info-lambda-list arg-info))))
  1601.  
  1602. (defmacro real-ensure-gf-internal (gf-class all-keys env)
  1603.   `(progn
  1604.      (cond ((symbolp ,gf-class)
  1605.         (setq ,gf-class (find-class ,gf-class t ,env)))
  1606.        ((classp ,gf-class))
  1607.        (t
  1608.         (error "The :GENERIC-FUNCTION-CLASS argument (~S) was neither a~%~
  1609.                     class nor a symbol that names a class."
  1610.            ,gf-class)))
  1611.      (remf ,all-keys :generic-function-class)
  1612.      (remf ,all-keys :environment)
  1613.      (let ((combin (getf ,all-keys :method-combination '.shes-not-there.)))
  1614.        (unless (eq combin '.shes-not-there.)
  1615.      (setf (getf ,all-keys :method-combination)
  1616.            (find-method-combination (class-prototype ,gf-class)
  1617.                     (car combin)
  1618.                     (cdr combin)))))
  1619.      ))
  1620.      
  1621. (defun real-ensure-gf-using-class--generic-function
  1622.        (existing
  1623.     function-specifier
  1624.     &rest all-keys
  1625.     &key environment (lambda-list nil lambda-list-p)
  1626.          (generic-function-class 'standard-generic-function gf-class-p)
  1627.     &allow-other-keys)
  1628.   #+copy-&rest-arg (setq all-keys (copy-list all-keys))
  1629.   (real-ensure-gf-internal generic-function-class all-keys environment)
  1630.   (unless (or (null gf-class-p)
  1631.           (eq (class-of existing) generic-function-class))
  1632.     (change-class existing generic-function-class))
  1633.   (prog1
  1634.       (apply #'reinitialize-instance existing all-keys)
  1635.     (when lambda-list-p
  1636.       (proclaim-defgeneric function-specifier lambda-list))))
  1637.  
  1638. (defun real-ensure-gf-using-class--null
  1639.        (existing
  1640.     function-specifier
  1641.     &rest all-keys
  1642.     &key environment (lambda-list nil lambda-list-p)
  1643.          (generic-function-class 'standard-generic-function)
  1644.     &allow-other-keys)
  1645.   (declare (ignore existing))
  1646.   #+copy-&rest-arg (setq all-keys (copy-list all-keys))
  1647.   (real-ensure-gf-internal generic-function-class all-keys environment)
  1648.   (prog1
  1649.       (setf (gdefinition function-specifier)
  1650.         (apply #'make-instance generic-function-class 
  1651.            :name function-specifier all-keys))
  1652.     (when lambda-list-p
  1653.       (proclaim-defgeneric function-specifier lambda-list))))
  1654.  
  1655.  
  1656.  
  1657. (defun get-generic-function-info (gf)
  1658.   ;; values   nreq applyp metatypes nkeys arg-info
  1659.   (multiple-value-bind (applyp metatypes arg-info)
  1660.       (let* ((arg-info (if (early-gf-p gf)
  1661.                (early-gf-arg-info gf)
  1662.                (gf-arg-info gf)))
  1663.          (metatypes (arg-info-metatypes arg-info)))
  1664.     (values (arg-info-applyp arg-info)
  1665.         metatypes
  1666.         arg-info))
  1667.     (values (length metatypes) applyp metatypes
  1668.         (count-if #'(lambda (x) (neq x 't)) metatypes)
  1669.         arg-info)))
  1670.  
  1671. (defun early-make-a-method (class qualifiers arglist specializers initargs doc
  1672.                 &optional slot-name)
  1673.   (initialize-method-function initargs)
  1674.   (let ((parsed ())
  1675.     (unparsed ()))
  1676.     ;; Figure out whether we got class objects or class names as the
  1677.     ;; specializers and set parsed and unparsed appropriately.  If we
  1678.     ;; got class objects, then we can compute unparsed, but if we got
  1679.     ;; class names we don't try to compute parsed.
  1680.     ;; 
  1681.     ;; Note that the use of not symbolp in this call to every should be
  1682.     ;; read as 'classp' we can't use classp itself because it doesn't
  1683.     ;; exist yet.
  1684.     (if (every #'(lambda (s) (not (symbolp s))) specializers)
  1685.     (setq parsed specializers
  1686.           unparsed (mapcar #'(lambda (s)
  1687.                    (if (eq s 't) 't (class-name s)))
  1688.                    specializers))
  1689.     (setq unparsed specializers
  1690.           parsed ()))
  1691.     (list :early-method          ;This is an early method dammit!
  1692.       
  1693.       (getf initargs ':function)
  1694.       (getf initargs ':fast-function)
  1695.       
  1696.       parsed                  ;The parsed specializers.  This is used
  1697.                   ;by early-method-specializers to cache
  1698.                   ;the parse.  Note that this only comes
  1699.                   ;into play when there is more than one
  1700.                   ;early method on an early gf.
  1701.       
  1702.       (list class             ;A list to which real-make-a-method
  1703.         qualifiers        ;can be applied to make a real method
  1704.         arglist           ;corresponding to this early one.
  1705.         unparsed
  1706.         initargs
  1707.         doc
  1708.         slot-name)
  1709.       )))
  1710.  
  1711. (defun real-make-a-method
  1712.        (class qualifiers lambda-list specializers initargs doc
  1713.     &optional slot-name)
  1714.   (setq specializers (parse-specializers specializers))
  1715.   (apply #'make-instance class 
  1716.      :qualifiers qualifiers
  1717.      :lambda-list lambda-list
  1718.      :specializers specializers
  1719.      :documentation doc
  1720.      :slot-name slot-name
  1721.      :allow-other-keys t
  1722.      initargs))
  1723.  
  1724. (defun early-method-function (early-method)
  1725.   (values (cadr early-method) (caddr early-method)))
  1726.  
  1727. (defun early-method-class (early-method)
  1728.   (find-class (car (fifth early-method))))
  1729.  
  1730. (defun early-method-standard-accessor-p (early-method)
  1731.   (let ((class (first (fifth early-method))))
  1732.     (or (eq class 'standard-reader-method)
  1733.         (eq class 'standard-writer-method)
  1734.         (eq class 'standard-boundp-method))))
  1735.  
  1736. (defun early-method-standard-accessor-slot-name (early-method)
  1737.   (seventh (fifth early-method)))
  1738.  
  1739. ;;;
  1740. ;;; Fetch the specializers of an early method.  This is basically just a
  1741. ;;; simple accessor except that when the second argument is t, this converts
  1742. ;;; the specializers from symbols into class objects.  The class objects
  1743. ;;; are cached in the early method, this makes bootstrapping faster because
  1744. ;;; the class objects only have to be computed once.
  1745. ;;; NOTE:
  1746. ;;;  the second argument should only be passed as T by early-lookup-method.
  1747. ;;;  this is to implement the rule that only when there is more than one
  1748. ;;;  early method on a generic function is the conversion from class names
  1749. ;;;  to class objects done.
  1750. ;;;  the corresponds to the fact that we are only allowed to have one method
  1751. ;;;  on any generic function up until the time classes exist.
  1752. ;;;  
  1753. (defun early-method-specializers (early-method &optional objectsp)
  1754.   (if (and (listp early-method)
  1755.        (eq (car early-method) :early-method))
  1756.       (cond ((eq objectsp 't)
  1757.          (or (fourth early-method)
  1758.          (setf (fourth early-method)
  1759.                (mapcar #'find-class (cadddr (fifth early-method))))))
  1760.         (t
  1761.          (cadddr (fifth early-method))))
  1762.       (error "~S is not an early-method." early-method)))
  1763.  
  1764. (defun early-method-qualifiers (early-method)
  1765.   (cadr (fifth early-method)))
  1766.  
  1767. (defun early-method-lambda-list (early-method)
  1768.   (caddr (fifth early-method)))
  1769.  
  1770. (defun early-add-named-method (generic-function-name
  1771.                    qualifiers
  1772.                    specializers
  1773.                    arglist
  1774.                    &rest initargs)
  1775.   #+copy-&rest-arg (setq initargs (copy-list initargs))
  1776.   (let* ((gf (ensure-generic-function generic-function-name))
  1777.      (existing
  1778.        (dolist (m (early-gf-methods gf))
  1779.          (when (and (equal (early-method-specializers m) specializers)
  1780.             (equal (early-method-qualifiers m) qualifiers))
  1781.            (return m))))
  1782.      (new (make-a-method 'standard-method
  1783.                  qualifiers
  1784.                  arglist
  1785.                  specializers
  1786.                  initargs
  1787.                  ())))
  1788.     (when existing (remove-method gf existing))
  1789.     (add-method gf new)))
  1790.  
  1791. ;;;
  1792. ;;; This is the early version of add-method.  Later this will become a
  1793. ;;; generic function.  See fix-early-generic-functions which has special
  1794. ;;; knowledge about add-method.
  1795. ;;;
  1796. (defun add-method (generic-function method)
  1797.   (when (not (fsc-instance-p generic-function))
  1798.     (error "Early add-method didn't get a funcallable instance."))
  1799.   (when (not (and (listp method) (eq (car method) :early-method)))
  1800.     (error "Early add-method didn't get an early method."))
  1801.   (push method (early-gf-methods generic-function))
  1802.   (set-arg-info generic-function :new-method method)
  1803.   (unless (assoc (early-gf-name generic-function) *generic-function-fixups*
  1804.          :test #'equal)
  1805.     (update-dfun generic-function)))
  1806.  
  1807. ;;;
  1808. ;;; This is the early version of remove method.
  1809. ;;;
  1810. (defun remove-method (generic-function method)
  1811.   (when (not (fsc-instance-p generic-function))
  1812.     (error "Early remove-method didn't get a funcallable instance."))
  1813.   (when (not (and (listp method) (eq (car method) :early-method)))
  1814.     (error "Early remove-method didn't get an early method."))
  1815.   (setf (early-gf-methods generic-function)
  1816.     (remove method (early-gf-methods generic-function)))
  1817.   (set-arg-info generic-function)
  1818.   (unless (assoc (early-gf-name generic-function) *generic-function-fixups*
  1819.          :test #'equal)
  1820.     (update-dfun generic-function)))
  1821.  
  1822. ;;;
  1823. ;;; And the early version of get-method.
  1824. ;;;
  1825. (defun get-method (generic-function qualifiers specializers
  1826.                     &optional (errorp t))
  1827.   (if (early-gf-p generic-function)
  1828.       (or (dolist (m (early-gf-methods generic-function))
  1829.         (when (and (or (equal (early-method-specializers m nil)
  1830.                   specializers)
  1831.                (equal (early-method-specializers m 't)
  1832.                   specializers))
  1833.                (equal (early-method-qualifiers m) qualifiers))
  1834.           (return m)))
  1835.       (if errorp
  1836.           (error "Can't get early method.")
  1837.           nil))
  1838.       (real-get-method generic-function qualifiers specializers errorp)))
  1839.  
  1840. (defvar *fegf-debug-p* nil)
  1841.  
  1842. (defun fix-early-generic-functions (&optional (noisyp *fegf-debug-p*))
  1843.   (setq *fegf-started-p* t)
  1844.   (let ((accessors nil))
  1845.     ;; Rearrange *early-generic-functions* to speed up fix-early-generic-functions.
  1846.     (dolist (early-gf-spec *early-generic-functions*)
  1847.       (when (every #'early-method-standard-accessor-p
  1848.            (early-gf-methods (gdefinition early-gf-spec)))
  1849.     (push early-gf-spec accessors)))
  1850.     (dolist (spec (nconc accessors
  1851.              '(accessor-method-slot-name
  1852.                generic-function-methods
  1853.                method-specializers
  1854.                specializerp
  1855.                specializer-type
  1856.                specializer-class
  1857.                slot-definition-location
  1858.                slot-definition-name
  1859.                class-slots
  1860.                gf-arg-info
  1861.                class-precedence-list
  1862.                slot-boundp-using-class
  1863.                (setf slot-value-using-class)
  1864.                slot-value-using-class
  1865.                structure-class-p
  1866.                standard-class-p
  1867.                funcallable-standard-class-p
  1868.                specializerp)))
  1869.       (setq *early-generic-functions* 
  1870.         (cons spec (delete spec *early-generic-functions* :test #'equal))))
  1871.  
  1872.     (dolist (early-gf-spec *early-generic-functions*)
  1873.       (when noisyp (format t "~&~S..." early-gf-spec))
  1874.       (let* ((gf (gdefinition early-gf-spec))
  1875.          (methods (mapcar #'(lambda (early-method)
  1876.                   (let ((args (copy-list (fifth early-method))))
  1877.                     (setf (fourth args)
  1878.                       (early-method-specializers early-method t))
  1879.                     (apply #'real-make-a-method args)))
  1880.                   (early-gf-methods gf))))
  1881.     (setf (generic-function-method-class gf) *the-class-standard-method*)
  1882.     (setf (generic-function-method-combination gf) *standard-method-combination*)
  1883.     (set-methods gf methods)))
  1884.       
  1885.     (dolist (fns *early-functions*)
  1886.       (setf (gdefinition (car fns)) (symbol-function (caddr fns))))
  1887.       
  1888.     (dolist (fixup *generic-function-fixups*)
  1889.       (let* ((fspec (car fixup))
  1890.          (gf (gdefinition fspec))
  1891.          (methods (mapcar #'(lambda (method)
  1892.                   (let* ((lambda-list (first method))
  1893.                      (specializers (second method))
  1894.                      (method-fn-name (third method))
  1895.                      (fn-name (or method-fn-name fspec))
  1896.                      (fn (symbol-function fn-name))
  1897.                      (initargs 
  1898.                       (list :function
  1899.                         (set-function-name
  1900.                          #'(lambda (args next-methods)
  1901.                              (declare (ignore next-methods))
  1902.                              (apply fn args))
  1903.                          `(call ,fn-name)))))
  1904.                     (declare (type function fn))
  1905.                     (make-a-method 'standard-method
  1906.                            ()
  1907.                            lambda-list
  1908.                            specializers
  1909.                            initargs
  1910.                            nil)))
  1911.                   (cdr fixup))))
  1912.     (setf (generic-function-method-class gf) *the-class-standard-method*)
  1913.     (setf (generic-function-method-combination gf) *standard-method-combination*)
  1914.     (set-methods gf methods)))))
  1915.  
  1916.  
  1917. ;;;
  1918. ;;; parse-defmethod is used by defmethod to parse the &rest argument into
  1919. ;;; the 'real' arguments.  This is where the syntax of defmethod is really
  1920. ;;; implemented.
  1921. ;;; 
  1922. (defun parse-defmethod (cdr-of-form)
  1923.   ;;(declare (values name qualifiers specialized-lambda-list body))
  1924.   (let ((name (pop cdr-of-form))
  1925.     (qualifiers ())
  1926.     (spec-ll ()))
  1927.     (loop (if (and (car cdr-of-form) (atom (car cdr-of-form)))
  1928.           (push (pop cdr-of-form) qualifiers)
  1929.           (return (setq qualifiers (nreverse qualifiers)))))
  1930.     (setq spec-ll (pop cdr-of-form))
  1931.     (values name qualifiers spec-ll cdr-of-form)))
  1932.  
  1933. (defun parse-specializers (specializers)
  1934.   (flet ((parse (spec)
  1935.        (let ((result (specializer-from-type spec)))
  1936.          (if (specializerp result)
  1937.          result
  1938.          (if (symbolp spec)
  1939.              (error "~S used as a specializer,~%~
  1940.                              but is not the name of a class."
  1941.                 spec)
  1942.              (error "~S is not a legal specializer." spec))))))
  1943.     (mapcar #'parse specializers)))
  1944.  
  1945. (defun unparse-specializers (specializers-or-method)
  1946.   (if (listp specializers-or-method)
  1947.       (flet ((unparse (spec)
  1948.            (if (specializerp spec)
  1949.                    (let ((type (specializer-type spec)))
  1950.                      (if (and (consp type)
  1951.                               (eq (car type) 'class))
  1952.                          (let* ((class (cadr type))
  1953.                                 (class-name (class-name class)))
  1954.                            (if (eq class (find-class class-name nil))
  1955.                                class-name
  1956.                                type))
  1957.                          type))
  1958.            (error "~S is not a legal specializer." spec))))
  1959.     (mapcar #'unparse specializers-or-method))
  1960.       (unparse-specializers (method-specializers specializers-or-method))))
  1961.  
  1962. (defun parse-method-or-spec (spec &optional (errorp t))
  1963.   ;;(declare (values generic-function method method-name))
  1964.   (let (gf method name temp)
  1965.     (if (method-p spec)    
  1966.     (setq method spec
  1967.           gf (method-generic-function method)
  1968.           temp (and gf (generic-function-name gf))
  1969.           name (if temp
  1970.                (intern-function-name
  1971.              (make-method-spec temp
  1972.                        (method-qualifiers method)
  1973.                        (unparse-specializers
  1974.                          (method-specializers method))))
  1975.                (make-symbol (format nil "~S" method))))
  1976.     (multiple-value-bind (gf-spec quals specls)
  1977.         (parse-defmethod spec)
  1978.       (and (setq gf (and (or errorp (gboundp gf-spec))
  1979.                  (gdefinition gf-spec)))
  1980.            (let ((nreq (compute-discriminating-function-arglist-info gf)))
  1981.          (setq specls (append (parse-specializers specls)
  1982.                       (make-list (- nreq (length specls))
  1983.                          :initial-element
  1984.                          *the-class-t*)))
  1985.          (and 
  1986.            (setq method (get-method gf quals specls errorp))
  1987.            (setq name
  1988.              (intern-function-name (make-method-spec gf-spec
  1989.                                  quals
  1990.                                  specls))))))))
  1991.     (values gf method name)))
  1992.  
  1993.  
  1994.  
  1995. (defun extract-parameters (specialized-lambda-list)
  1996.   (multiple-value-bind (parameters ignore1 ignore2)
  1997.       (parse-specialized-lambda-list specialized-lambda-list)
  1998.     (declare (ignore ignore1 ignore2))
  1999.     parameters))
  2000.  
  2001. (defun extract-lambda-list (specialized-lambda-list)
  2002.   (multiple-value-bind (ignore1 lambda-list ignore2)
  2003.       (parse-specialized-lambda-list specialized-lambda-list)
  2004.     (declare (ignore ignore1 ignore2))
  2005.     lambda-list))
  2006.  
  2007. (defun extract-specializer-names (specialized-lambda-list)
  2008.   (multiple-value-bind (ignore1 ignore2 specializers)
  2009.       (parse-specialized-lambda-list specialized-lambda-list)
  2010.     (declare (ignore ignore1 ignore2))
  2011.     specializers))
  2012.  
  2013. (defun extract-required-parameters (specialized-lambda-list)
  2014.   (multiple-value-bind (ignore1 ignore2 ignore3 required-parameters)
  2015.       (parse-specialized-lambda-list specialized-lambda-list)
  2016.     (declare (ignore ignore1 ignore2 ignore3))
  2017.     required-parameters))
  2018.  
  2019. (defun parse-specialized-lambda-list (arglist &optional post-keyword)
  2020.   ;;(declare (values parameters lambda-list specializers required-parameters))
  2021.   (let ((arg (car arglist)))
  2022.     (cond ((null arglist) (values nil nil nil nil))
  2023.       ((eq arg '&aux)
  2024.        (values nil arglist nil))
  2025.       ((memq arg lambda-list-keywords)
  2026.        (unless (memq arg '(&optional &rest &key &allow-other-keys &aux))
  2027.          ;; Warn about non-standard lambda-list-keywords, but then
  2028.          ;; go on to treat them like a standard lambda-list-keyword
  2029.          ;; what with the warning its probably ok.
  2030.          (warn "Unrecognized lambda-list keyword ~S in arglist.~%~
  2031.                     Assuming that the symbols following it are parameters,~%~
  2032.                     and not allowing any parameter specializers to follow~%~
  2033.                     to follow it."
  2034.            arg))
  2035.        ;; When we are at a lambda-list-keyword, the parameters don't
  2036.        ;; include the lambda-list-keyword; the lambda-list does include
  2037.        ;; the lambda-list-keyword; and no specializers are allowed to
  2038.        ;; follow the lambda-list-keywords (at least for now).
  2039.        (multiple-value-bind (parameters lambda-list)
  2040.            (parse-specialized-lambda-list (cdr arglist) t)
  2041.          (values parameters
  2042.              (cons arg lambda-list)
  2043.              ()
  2044.              ())))
  2045.       (post-keyword
  2046.        ;; After a lambda-list-keyword there can be no specializers.
  2047.        (multiple-value-bind (parameters lambda-list)
  2048.            (parse-specialized-lambda-list (cdr arglist) t)           
  2049.          (values (cons (if (listp arg) (car arg) arg) parameters)
  2050.              (cons arg lambda-list)
  2051.              ()
  2052.              ())))
  2053.       (t
  2054.        (multiple-value-bind (parameters lambda-list specializers required)
  2055.            (parse-specialized-lambda-list (cdr arglist))
  2056.          (values (cons (if (listp arg) (car arg) arg) parameters)
  2057.              (cons (if (listp arg) (car arg) arg) lambda-list)
  2058.              (cons (if (listp arg) (cadr arg) 't) specializers)
  2059.              (cons (if (listp arg) (car arg) arg) required)))))))
  2060.  
  2061.  
  2062. (eval-when (load eval)
  2063.   (setq *boot-state* 'early))
  2064.  
  2065.  
  2066. #-cmu ;; CMUCL Has a real symbol-macrolet
  2067. (progn
  2068. (defmacro symbol-macrolet (bindings &body body &environment env)
  2069.   (let ((specs (mapcar #'(lambda (binding)
  2070.                (list (car binding)
  2071.                  (variable-lexical-p (car binding) env)
  2072.                  (cadr binding)))
  2073.                bindings)))
  2074.     (walk-form `(progn ,@body)
  2075.            env
  2076.            #'(lambda (f c e)
  2077.            (expand-symbol-macrolet-internal specs f c e)))))
  2078.  
  2079. (defun expand-symbol-macrolet-internal (specs form context env)
  2080.   (let ((entry nil))
  2081.     (cond ((not (eq context :eval)) form)
  2082.       ((symbolp form)
  2083.        (if (and (setq entry (assoc form specs))
  2084.             (eq (cadr entry) (variable-lexical-p form env)))
  2085.            (caddr entry)
  2086.            form))
  2087.       ((not (listp form)) form)
  2088.       ((member (car form) '(setq setf))
  2089.        ;; Have to be careful.  We must only convert the form to a SETF
  2090.        ;; form when we convert one of the 'logical' variables to a form
  2091.        ;; Otherwise we will get looping in implementations where setf
  2092.        ;; is a macro which expands into setq.
  2093.        (let ((kind (car form)))
  2094.          (labels ((scan-setf (tail)
  2095.             (if (null tail)
  2096.                 nil
  2097.                 (walker::relist*
  2098.                   tail
  2099.                   (if (and (setq entry (assoc (car tail) specs))
  2100.                        (eq (cadr entry)
  2101.                        (variable-lexical-p (car tail)
  2102.                                    env)))
  2103.                   (progn (setq kind 'setf)
  2104.                      (caddr entry))
  2105.                   (car tail))
  2106.                   (cadr tail)
  2107.                   (scan-setf (cddr tail))))))
  2108.            (let (new-tail)
  2109.          (setq new-tail (scan-setf (cdr form)))
  2110.          (walker::recons form kind new-tail)))))
  2111.       ((eq (car form) 'multiple-value-setq)
  2112.        (let* ((vars (cadr form))
  2113.           (gensyms (mapcar #'(lambda (i) (declare (ignore i)) (gensym))
  2114.                    vars)))
  2115.          `(multiple-value-bind ,gensyms 
  2116.           ,(caddr form)
  2117.         .,(reverse (mapcar #'(lambda (v g) `(setf ,v ,g))
  2118.                    vars
  2119.                    gensyms)))))
  2120.       (t form))))
  2121. )
  2122.  
  2123. (defmacro with-slots (slots instance &body body)
  2124.   (let ((in (gensym)))
  2125.     `(let ((,in ,instance))
  2126.        #+cmu (declare (ignorable ,in))
  2127.        ,@(let ((instance (if (and (consp instance) (eq (car instance) 'the))
  2128.                              (third instance)
  2129.                              instance)))
  2130.        (and (symbolp instance)
  2131.                 `((declare (variable-rebinding ,in ,instance)))))
  2132.        ,in
  2133.        (symbol-macrolet ,(mapcar #'(lambda (slot-entry)
  2134.                      (let ((variable-name 
  2135.                         (if (symbolp slot-entry)
  2136.                         slot-entry
  2137.                         (car slot-entry)))
  2138.                        (slot-name
  2139.                         (if (symbolp slot-entry)
  2140.                         slot-entry
  2141.                         (cadr slot-entry))))
  2142.                        `(,variable-name
  2143.                       (slot-value ,in ',slot-name))))
  2144.                  slots)
  2145.             ,@body))))
  2146.  
  2147. (defmacro with-accessors (slots instance &body body)
  2148.   (let ((in (gensym)))
  2149.     `(let ((,in ,instance))
  2150.        #+cmu (declare (ignorable ,in))
  2151.        ,@(let ((instance (if (and (consp instance) (eq (car instance) 'the))
  2152.                              (third instance)
  2153.                              instance)))
  2154.        (and (symbolp instance)
  2155.                 `((declare (variable-rebinding ,in ,instance)))))
  2156.        ,in
  2157.        (symbol-macrolet ,(mapcar #'(lambda (slot-entry)
  2158.                    (let ((variable-name (car slot-entry))
  2159.                      (accessor-name (cadr slot-entry)))
  2160.                      `(,variable-name
  2161.                         (,accessor-name ,in))))
  2162.                    slots)
  2163.           ,@body))))
  2164.  
  2165.  
  2166.  
  2167.